const path = require('path') // nodeJS 核心模块，处理路径
const ESLintPlugin = require('eslint-webpack-plugin') // ESLint 插件
const HtmlWebpackPlugin = require('html-webpack-plugin'); // HTML 打包插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // CSS 单独打包插件(使用 link 引入 CSS，避免使用 style 标签实现样式从而导致的卡顿)
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') // CSS 压缩插件

const getStyleLoaders = (preProcessor) => {
    return [  // 设置多个 loader
        MiniCssExtractPlugin.loader, // MiniCssExtractPlugin.loader 使用该插件d的 loader 将css 转换为的 js，单独打包成 CSS 输出 （style-loader：将 js 中 css 通过创建 style 标签的方式添加到 html 文件中生效）
        "css-loader", // 将 css 资源编译成 commonJS 的模块到 js 中
        {
            loader: "postcss-loader",  // 用以解决样式兼容性问题，需要加载 css-loader 之后，less-loader、sass-loader、styl-loader 之前
            options: {
                postcssOptions: {
                    plugins: [
                        "postcss-preset-env" // 使用预设
                    ]
                }
            }
        },
        preProcessor
    ].filter(Boolean) // 去除掉 undefined 项
}

module.exports = {
    // Webpack 打包入口
    entry: './src/main.js', // 相对路径，相对于命令执行处的路径，不需要改变
    // Webpack 打包输出位置
    output: {
        // 文件输出路径
        // __dirname nodeJS 变量，代表当前文件所在文件夹路径
        path: path.resolve(__dirname, '../dist'), // 绝对路径 path.resolve(a, b) 拼接路径： ab *** 注意：此文件在文件夹内部，__dirname 为文件夹路径，需要往外面退一个层级 ***
        // 入口文件输出的文件名
        filename: 'js/main.js',
        // 自动清空上次打爆包的内容
        // 原理：在打包前，将 path 整个目录内容清空，再进行打包
        clean: true
    },
    // 加载器
    module: {
        rules: [
            // 加载器配置
            {
                test: /\.css$/, // 匹配以 .css 结尾的文件
                //loader: 'css-loader', // 只能设置单个 loader
                use: getStyleLoaders()
                // [  // 设置多个 loader
                //     MiniCssExtractPlugin.loader, // MiniCssExtractPlugin.loader 使用该插件d的 loader 将css 转换为的 js，单独打包成 CSS 输出 （style-loader：将 js 中 css 通过创建 style 标签的方式添加到 html 文件中生效）
                //     "css-loader", // 将 css 资源编译成 commonJS 的模块到 js 中
                //     {
                //         loader: "postcss-loader",  // 用以解决样式兼容性问题，需要加载 css-loader 之后，less-loader、sass-loader、styl-loader 之前
                //         options: {
                //             postcssOptions: {
                //                 plugins: [
                //                     "postcss-preset-env" // 使用预设
                //                 ]
                //             }
                //         }
                //     },
                //     preProcessor
                // ] loader 自下而上加载
            },
            {
                test: /\.less$/,
                use: getStyleLoaders('less-loader')
                // [
                //     MiniCssExtractPlugin.loader,
                //     'css-loader',
                //     {
                //         loader: "postcss-loader",  // 用以解决样式兼容性问题，需要加载 css-loader 之后，less-loader、sass-loader、styl-loader 之前
                //         options: {
                //             postcssOptions: {
                //                 plugins: [
                //                     "postcss-preset-env" // 使用预设
                //                 ]
                //             }
                //         }
                //     },
                //     'less-loader', // compiles Less to CSS
                // ],
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders('sass-loader')
                // [
                //     MiniCssExtractPlugin.loader,
                //     'css-loader',
                //     {
                //         loader: "postcss-loader",  // 用以解决样式兼容性问题，需要加载 css-loader 之后，less-loader、sass-loader、styl-loader 之前
                //         options: {
                //             postcssOptions: {
                //                 plugins: [
                //                     "postcss-preset-env" // 使用预设
                //                 ]
                //             }
                //         }
                //     },
                //     'sass-loader', // 将 Sass 编译成 CSS
                // ],
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders('stylus-loader')
                // [
                //     MiniCssExtractPlugin.loader,
                //     'css-loader',
                //     {
                //         loader: "postcss-loader",  // 用以解决样式兼容性问题，需要加载 css-loader 之后，less-loader、sass-loader、styl-loader 之前
                //         options: {
                //             postcssOptions: {
                //                 plugins: [
                //                     "postcss-preset-env" // 使用预设
                //                 ]
                //             }
                //         }
                //     },
                //     'stylus-loader', // 将 Stylus 编译成 CSS
                // ],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,  // 处理图片
                type: 'asset',
                parser: {
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于 10kb 的图片会被解析成 base64 放在 url 中。 优点：减少请求数量 缺点：文件体积会变大
                    }
                },
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                }
            },
            {
                test: /\.(ttf|woff2?|mp3|mp4|avi)$/,  // 处理图标 音视频等其他类型文件（不需要处理，只原封不动地输出）
                type: 'asset/resource',
                generator: {
                    // 将图标文件输出到 static/media 目录中
                    // 将图标文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/media/[hash:8][ext][query]",
                }
            },
            {
                test: /\.m?js$/, // 处理 js
                exclude: /(node_modules|bower_components)/, // 排除 node_module 内的 js 代码 
                use: {
                    loader: 'babel-loader', // 使用 babel 编译器
                    //   options: { //可使用 options 指定 babel 规则，也可以不写，通过配置文件设置 babel 规则
                    //     presets: ['@babel/preset-env'] // 使用预设
                    //   }
                }
            }
        ]
    },
    // 插件
    plugins: [
        new ESLintPlugin({  // ESLint 语法检查插件
            context: path.resolve(__dirname, '../src')
        }),
        new HtmlWebpackPlugin({ // 自动生成 HTML 资源，并且引入打包的 js
            template: path.resolve(__dirname, '../public/index.html') // 使用指定路径的 HTML 文件作为模板，生成的 HTML 资源跟模板相同，并且引入了打包的 js 资源
        }),
        new MiniCssExtractPlugin({
            filename: 'static/main.css'  // 指定单独打包的 CSS 存放目录
        }),
        new CssMinimizerPlugin() // 压缩打包的 CSS 文件
    ],
    // 模式：
    // -- development: 1.打包代码
    // -- production: 1.打包代码 2.压缩代码
    mode: 'production',
    // *** 生产模式不需要开启 devServer，故不会对 devServer 进行配置 ***
}